/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved.
 */

package com.huawei.chengdu.meetingdemo.presenter;

import com.device.idea.meeting.Addressbook.model.AddrBookNetUserInfo;
import com.device.idea.meeting.Addressbook.model.AddrBookUserInfo;
import com.huawei.chengdu.meetingdemo.callback.MeetingCallbackSelf;
import com.huawei.chengdu.meetingdemo.consts.ObserverConts;
import com.huawei.chengdu.meetingdemo.model.AddrBookBean;
import com.huawei.chengdu.meetingdemo.util.AppContext;
import com.huawei.chengdu.meetingdemo.util.LogUtil;
import com.huawei.chengdu.meetingdemo.util.RelTimer;
import com.huawei.chengdu.meetingdemo.util.ThreadPool;

import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;

public class AddressBookPresenter {
    /**
     * 空闲态未执行搜索
     */
    public static final int IDLE = 0;

    /**
     * 加入会议搜索
     */
    public static final int SEARCH_JOIN_MEETING = 1;

    /**
     * 联系人搜索
     */
    public static final int SEARCH_CONTACTS = 2;

    /**
     * 邀请入会联系人搜索
     */
    public static final int SEARCH_MEETING = 3;
    private static final int RSP_OK_CODE = 0;
    private static final String TAG = "AddressBookPresenter";

    private static final int WAITING_TIME = 1000;

    private CopyOnWriteArrayList<AddrBookBean> list = new CopyOnWriteArrayList<>();

    private RelTimer timer;

    /**
     * 搜索来源
     * 0 空闲态未执行搜索
     * 1 会前 加入会议搜索
     * 2 会前 联系人搜索
     */
    private int searchSource = IDLE;

    private int search = 0;

    private String str;

    /**
     * 需要等待搜索的集合
     */
    private List<Search> waitingSearch = new ArrayList<>();

    private Future<Boolean> future;

    public AddressBookPresenter() {
    }

    /**
     * 各个页面发起地址本搜索 包含本地跟网络地址本
     *
     * @param str          搜索关键字
     * @param searchSource 页面操作码
     * @param isAutoFlag 是否默认页面搜索
     */
    public void addressBookSearch(String str, int searchSource, boolean isAutoFlag) {
        LogUtil.info(TAG + "search:" + search + " searchSource:" + searchSource);
        LogUtil.info(TAG + "addressBookSearch () , this.searchSource " + this.searchSource);
        if (search < 0) { // 本身不应该出现回调比调用搜索次数还多的情况
            search = 0;
        }
        if (search == 0) {
            this.searchSource = searchSource;
            if (future != null) {
                future.cancel(true);
                future = null;
            }
            this.str = str;
            future = ThreadPool.getInstance().submit(new SearchRunnable(str, isAutoFlag));
        } else { // 上一个搜索界面搜索未结束
            waitingSearch.add(new Search(searchSource, str, isAutoFlag));
            startTimer();
        }
    }

    private void startTimer() {
        if (timer != null) {
            return;
        }
        timer = new RelTimer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (waitingSearch.size() == 0) {
                    stopTimer();
                    return;
                }
                search(waitingSearch.get(0).str, waitingSearch.get(0).searchSource, waitingSearch.get(0).isAutoFlag);
                waitingSearch.remove(0);
            }
        }, WAITING_TIME, WAITING_TIME);
    }

    private void search(String str, int searchSource, boolean isAutoFlag) {
        LogUtil.info(TAG + "searchSource:" + searchSource);
        list.clear();
        int faultNo;
        if ("".equals(str)) { // 查找所有联系人
            faultNo = ConfSdkPresenter.searchAllLocalUsers(new MeetingCallbackSelf<List<AddrBookUserInfo>>(TAG + " searchAllUsers") {
                // 统一在MeetingControlEventCallback中处理，这里不重复处理
                @Override
                public void onSuccess(List<AddrBookUserInfo> addrBookUserInfos) {}
                @Override
                public void onFailed(int errCode, String errMsg) {}
            }.getMeetingCallback());
        } else {
            faultNo = ConfSdkPresenter.searchLocalUserByKeyword(str, new MeetingCallbackSelf<List<AddrBookUserInfo>>(TAG + " searchUserByKeyWord") {
                // 统一在MeetingControlEventCallback中处理，这里不重复处理
                @Override
                public void onSuccess(List<AddrBookUserInfo> addrBookUserInfos) {}
                @Override
                public void onFailed(int errCode, String errMsg) {}
            }.getMeetingCallback());
        }
        search++;
        if (faultNo != RSP_OK_CODE) {
            LogUtil.error(TAG + "startTimer() searchSource:" + searchSource);
            noticeDataChange(searchSource);
        } else {
            AddressBookPresenter.this.searchSource = searchSource;
            AddressBookPresenter.this.str = str;
        }
        // LDAP默认搜索是否开启，没有开启不搜索网络地址本
        if (!isAutoFlag) {
            LogUtil.info(TAG + "searchNetAddressBookInfo()");
            search++;
            faultNo = ConfSdkPresenter.searchCompanyUsers("".equals(str) ? "*" : str, new MeetingCallbackSelf<List<AddrBookNetUserInfo>>(TAG + " searchNetAddressBookInfo") {
                // 统一在MeetingControlEventCallback中处理，这里不重复处理
                @Override
                public void onSuccess(List<AddrBookNetUserInfo> addrBookNetUserInfos) {}
                @Override
                public void onFailed(int errCode, String errMsg) {}
            }.getMeetingCallback());
            if (faultNo != RSP_OK_CODE) {
                LogUtil.error(TAG + "startTimer() searchSource:" + searchSource);
                noticeDataChange(searchSource);
                AddressBookPresenter.this.searchSource = IDLE;
                AddressBookPresenter.this.str = "";
            } else {
                AddressBookPresenter.this.searchSource = searchSource;
                AddressBookPresenter.this.str = str;
            }
        }
    }

    /**
     * 地址本查询联系人返回结果
     *
     * @param userInfo 地址本列表
     */
    public void onAddressBookUserResult(List<AddrBookUserInfo> userInfo) {
        int resultSize = (userInfo == null) ? 0 : userInfo.size();
        LogUtil.info(TAG + "onAddressBookUserResult() ->AddrBookUserInfo list size:" + resultSize);
        search--;
        if (userInfo != null) {
            for (AddrBookUserInfo info : userInfo) {
                list.add(new AddrBookBean(info));
            }
        }
        noticeDataChange(searchSource);
    }

    /**
     * 地址本查询本地所有联系人返回结果
     *
     * @param userInfo 地址本列表
     */
    public void onAddressBookAllUserResult(List<AddrBookUserInfo> userInfo) {
        int resultSize = (userInfo == null) ? 0 : userInfo.size();
        LogUtil.info(TAG + "onAddressBookAllUserResult() ->AddrBookUserInfo list size:" + resultSize);
        search--;
        if (userInfo != null) {
            for (AddrBookUserInfo info : userInfo) {
                list.add(new AddrBookBean(info));
            }
        }
        noticeDataChange(searchSource);
    }

    /**
     * 地址本查询网络联系人返回结果
     *
     * @param userInfo 地址本列表
     */
    public void onAddressBookNetUserResult(List<AddrBookNetUserInfo> userInfo) {
        int resultSize = (userInfo == null) ? 0 : userInfo.size();
        LogUtil.info(TAG + "onAddressBookNetUserResult() ->AddrBookNetUserInfo list size:" + resultSize);
        search--;
        if (userInfo != null) {
            for (AddrBookNetUserInfo info : userInfo) {
                list.add(new AddrBookBean(info));
            }
        }
        noticeDataChange(searchSource);
        this.searchSource = IDLE;
    }

    private void noticeDataChange(int searchSource) {
        LogUtil.info(TAG + "noticeDataChange() , searchSource : " + searchSource);
        int msgid = 0;
        if (searchSource == SEARCH_JOIN_MEETING) {
            msgid = ObserverConts.DATA_LOCAL_AND_LDAP_JOIN_CONF_SEARCH_SITE;
        }
        if (searchSource == SEARCH_CONTACTS || searchSource == SEARCH_MEETING) {
            msgid = ObserverConts.DATA_LOCAL_AND_LDAP_SEARCH_SITE;
        }
        if (msgid == 0) {
            return;
        }
        if (msgid == ObserverConts.DATA_LOCAL_AND_LDAP_SEARCH_SITE) {
            AppContext.instance().rbServ.searchAddrBookUserList.clear();
            AppContext.instance().rbServ.searchAddrBookUserList.addAll(list);
        }
        if (msgid == ObserverConts.DATA_LOCAL_AND_LDAP_JOIN_CONF_SEARCH_SITE) {
            AppContext.instance().rbServ.searchSiteList.clear();
            AppContext.instance().rbServ.searchSiteList.addAll(list);
        }
        LogUtil.info(TAG + msgid + " searchAddrBookUserList size"
                + AppContext.instance().rbServ.searchAddrBookUserList.size());
        LogUtil.info(TAG + msgid + " searchSiteList size" + AppContext.instance().rbServ.searchSiteList.size());
        AppContext.instance().rbServ.noticeDataChange(msgid, null);
    }

    private void stopTimer() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    private static class Search {
        private Integer searchSource;

        private String str;

        private boolean isAutoFlag;

        public Search(Integer searchSource, String str, boolean isAutoFlag) {
            this.searchSource = searchSource;
            this.str = str;
            this.isAutoFlag = isAutoFlag;
        }
    }

    class SearchRunnable implements Runnable {
        private String str;
        private boolean isAutoFlag;

        public SearchRunnable(String str, boolean isAutoFlag) {
            SearchRunnable.this.str = str;
            SearchRunnable.this.isAutoFlag = isAutoFlag;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException exception) {
                LogUtil.error(TAG + "addressBookSearch() InterruptedException");
            }
            if (SearchRunnable.this.str == null || !SearchRunnable.this.str.equals(AddressBookPresenter.this.str)) {
                return;
            }
            search(str, searchSource, isAutoFlag);
        }
    }

}
